#import "MRHudView.h"

#define     DEFAULT_AFTERDELAY      0.7

/*===================================================================
 说明:
    指示器层
 ==================================================================*/
@implementation HUDImageLayer

#define IMG_SUCCESS @".849#.115/.382#.582/.152#.351/0#.503/.382#.885/1#.267"
#define IMG_FAILURE @"1#.236/.764#0/.5#.264/.236#0/0#.236/.264#.5/0#.764/.236#1/.5#.736/.764#1/1#.764/.736#.5"

//@dynamic progress, imgStyle;

- (void)setImgStyle:(HUDIMAGESTYLE)imgStyle
{
	_imgStyle = imgStyle;
	[self setNeedsDisplay];
}

+ (BOOL)needsDisplayForKey:(NSString *)key
{
    return [key isEqualToString:@"progress"] || [super needsDisplayForKey:key];
}

- (id<CAAction>)actionForKey:(NSString *)key
{
    if ([key isEqualToString:@"progress"] && self.progress == 0)
    {
        CABasicAnimation *progressAnimation = [CABasicAnimation animation];
        //progressAnimation.duration  = .25;
        progressAnimation.fromValue = [self.presentationLayer valueForKey:key];
        progressAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
        return progressAnimation;
    }
    return [super actionForKey:key];
}

- (void)drawInContext:(CGContextRef)ctx
{
    CGRect rect = CGRectInset(CGRectIntegral(self.bounds), 0, 0);
    
    UIGraphicsPushContext(ctx);
    
    UIBezierPath *path = [UIBezierPath bezierPath];
    if (self.imgStyle == IMAGE_PROGRESS)  //环形进度
    {
        //创建进度圆形路径(圆环形)
        CGRect insetRect = CGRectInset(rect, 0, 0);
        UIBezierPath *circlePath = [UIBezierPath bezierPathWithOvalInRect:rect];
        UIBezierPath *innerCirclePath = [UIBezierPath bezierPathWithOvalInRect:CGRectInset(rect, 9, 9)];
        
        [circlePath appendPath:innerCirclePath];
        [circlePath setUsesEvenOddFillRule:YES];
        [circlePath addClip];
        
        //填充进度区域背影
        [[UIColor colorWithWhite:1.0 alpha:0.2] setFill];
        [circlePath fill];
        
        //环形进度条
        CGFloat radius = truncf(MIN(CGRectGetMidX(insetRect), CGRectGetMidY(insetRect))) + ((self.contentsScale > 1) ? 0.5f : 0.f);
        CGPoint center = CGPointMake(CGRectGetMidX(insetRect), CGRectGetMidY(insetRect));
        [path moveToPoint:center];
        [path addArcWithCenter:center radius:radius startAngle:-M_PI_2 endAngle:(2.f * self.progress - 0.5)*M_PI clockwise:YES];
        [path closePath];
        
        //绘制边框
        [[UIColor colorWithWhite:1.f alpha:0.5f] setStroke];
        [circlePath stroke];
        [innerCirclePath stroke];
    }
    else    //成功或失败图形
    {
        NSString *pointsString = (self.imgStyle == IMAGE_SUCCESS) ? IMG_SUCCESS : IMG_FAILURE;
        NSArray  *pointsArray  = [pointsString componentsSeparatedByString:@"/"];
        
        for (NSString *point in pointsArray)
        {
            NSArray *vPoint = [point componentsSeparatedByString:@"#"];
            CGPoint newPoint = CGPointMake([vPoint[0] floatValue] * rect.size.width, [vPoint[1] floatValue] * rect.size.height);
            
            if ([path isEmpty]) [path moveToPoint:newPoint]; else [path addLineToPoint:newPoint];
        }
        
        [path closePath];
    }
    
    //填充路径
    if (![path isEmpty])
    {
        [[UIColor whiteColor] setFill];
        [path fill];
    }
    
    UIGraphicsPopContext();
}
@end

/*===================================================================
 说明:
    指示器图像类
 ==================================================================*/
@implementation HUDImageView

- (void)awakeFromNib
{
	[super awakeFromNib];
	
	_imgLayer = [HUDImageLayer layer];
	_imgLayer.frame = self.bounds;
	_imgLayer.contentsScale = [UIScreen mainScreen].scale;
	[self.layer addSublayer:_imgLayer];
	
	_imgLayer.imgStyle = IMAGE_SUCCESS;
}

@end

#pragma mark - 弹出视图

/*===================================================================
 说明:
    弹出式控制器
 ==================================================================*/
@implementation MRPopupView

- (id)init
{
    if (self = [super init])
    {
		self.hidden = YES;
		
		//遮罩层
        _overlay = [[UIImageView alloc] init];
		_overlay.alpha = 0;
		_overlay.userInteractionEnabled = YES;
        _overlay.backgroundColor = rgba(0,0,0, .3);
		_overlay.translatesAutoresizingMaskIntoConstraints = NO;
		
		//_blurRadius = -1;
		_blurRadius = [UIScreen mainScreen].scale * 5;		//初始模拟半径
		_blurColor  = [MRSkinManager skin].nightMode ? rgba(0,0,0, .3) : rgba(0,0,0, .1);
		
		_clickDismiss = YES;
		
		_constraints = [self addConstraintEqualSuperview:_overlay];
    }
	
    return self;
}

/*===================================================================
 说明:
    显示弹出窗口
 ==================================================================*/
- (void)showView:(UIView *)view style:(MRPopupSytle)style
{
    [self showView:view superview:nil style:style handler:nil];
}

- (void)showView:(UIView *)view style:(MRPopupSytle)style size:(CGSize)size
{
	[self showView:view superview:nil style:style size:size handler:nil];
}

- (void)showView:(UIView *)view superview:(UIView *)superview style:(MRPopupSytle)style
{
	[self showView:view superview:superview style:style handler:nil];
}

- (void)showView:(UIView *)view superview:(UIView *)superview style:(MRPopupSytle)style handler:(DismissHandler)handler
{
	[self showView:view superview:superview style:style size:CGSizeMake(.8, 0) handler:handler];
}

- (void)showView:(UIView *)view superview:(UIView *)superview style:(MRPopupSytle)style size:(CGSize)size handler:(DismissHandler)handler
{
    _style = style;
	_handler = handler;
	
	if (!superview) superview = [UIApplication sharedApplication].keyWindow;
	
	if (_blurRadius > 0)	//模糊背景
	{
		_overlay.image = [UIImage imageForView:superview];
		dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
			UIImage *image = [_overlay.image blurWithRadius:_blurRadius tintColor:_blurColor];
			dispatch_async(dispatch_get_main_queue(), ^{_overlay.image = image;});
		});
	}
	
	//从View的父窗口移除有关View的layout，否则有可能引出冲突造成异常
    _superView = view.superview;
	_constraint = [view getConstraintFromSuperview];
    [view removeConstraintFromSuperview];
	[_overlay addConstraintEqualSuperview:superview];
	
	UIViewController *superVC = superview.viewController;
	if (superVC)	//含有控制器时，不包含透明的导航栏及标签栏
	{
		_constraints[0].constant = superVC.topLayoutGuide.length - PIXEL(1);
		_constraints[1].constant = superVC.bottomLayoutGuide.length;
	}
	
	view.translatesAutoresizingMaskIntoConstraints = NO;
	view.hidden = NO;
	self.hidden = NO;
	
	[self addSubview:view];
	[self setShadowWithRadius:(_blurRadius > 0 ? 0 : 5) color:rgba(0,0,0, .3) path:nil];
    
    //初始化位置
	NSMutableArray <NSLayoutConstraint *> *constraints = [NSMutableArray array];
	
    switch (_style)
    {
        case MRPopupStyleTop:
            _layoutControl = [NSLayoutConstraint constraintWithItem:view attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeTop multiplier:1 constant:0];
			[constraints addObject:_layoutControl];
			[constraints addObject:[NSLayoutConstraint constraintWithItem:view attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeLeft multiplier:1 constant:0]];
            [constraints addObject:[NSLayoutConstraint constraintWithItem:view attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeRight multiplier:1 constant:0]];
            break;
            
        case MRPopupStyleBottom:
            _layoutControl = [NSLayoutConstraint constraintWithItem:view attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeBottom multiplier:1 constant:0];
			[constraints addObject:_layoutControl];
			[constraints addObject:[NSLayoutConstraint constraintWithItem:view attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeLeft multiplier:1 constant:0]];
            [constraints addObject:[NSLayoutConstraint constraintWithItem:view attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeRight multiplier:1 constant:0]];
            break;
            
        case MRPopupStyleAlert:
			[constraints addObject:[NSLayoutConstraint constraintWithItem:view attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeCenterX multiplier:1 constant:0]];
			[constraints addObject:[NSLayoutConstraint constraintWithItem:view attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeCenterY multiplier:1 constant:0]];
			
			//
			if (size.width > 1)
				[constraints addObject:[NSLayoutConstraint constraintWithItem:view attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1 constant:size.width]];
			else if (size.width > 0)
				[constraints addObject:[NSLayoutConstraint constraintWithItem:view attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeWidth multiplier:size.width constant:0]];
			
			//
			if (size.height > 1)
				[constraints addObject:[NSLayoutConstraint constraintWithItem:view attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1 constant:size.height]];
			else if (size.height > 0)
				[constraints addObject:[NSLayoutConstraint constraintWithItem:view attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeHeight multiplier:size.height constant:0]];
			
			
			view.transform = CGAffineTransformMakeScale(1.3, 1.3);
            break;
    }
	
	[self addConstraints:constraints];
	[self layoutIfNeeded];
	
    //动画
    [UIView animateWithDuration:.25 animations:^{
        
        switch (_style)
        {
            case MRPopupStyleAlert:   view.transform = CGAffineTransformIdentity;         break;
            case MRPopupStyleTop:     _layoutControl.constant = view.bounds.size.height;  break;
            case MRPopupStyleBottom:  _layoutControl.constant = -view.bounds.size.height; break;
        }
        _overlay.alpha = 1;
        [self layoutIfNeeded];
    }];
}

/*===================================================================
 说明:
	移除窗口
 ==================================================================*/
- (void)willRemoveSubview:(UIView *)subview
{
	if (!self.hidden) [self dismiss];
}

/*===================================================================
 说明:
    隐藏弹出窗口
 ==================================================================*/
- (void)dismiss
{
	[self dismissWithAnimated:YES];
}

- (void)dismissWithAnimated:(BOOL)animated
{
	[self dismissWithAnimated:animated user:YES];
}

- (void)dismissWithAnimated:(BOOL)animated user:(BOOL)user
{
    if (self.hidden) return;
	
	__weak UIView *this = self;
	__weak UIView *view = self.subviews.firstObject;
	
	if (_handler)
	{
		_handler(NO, user);		//将要结束
	}
	
    [UIView animateWithDuration:(animated ? .25 : 0) animations:^{
        
        _overlay.alpha = 0;
        switch (_style)
        {
            case MRPopupStyleTop:     _layoutControl.constant = 0;    break;
            case MRPopupStyleBottom:  _layoutControl.constant = 0;    break;
            case MRPopupStyleAlert:   view.transform = CGAffineTransformMakeScale(.7, .7); break;
        }
        [this layoutIfNeeded];
        
    } completion:^(BOOL finished) {
		
		this.hidden = YES;
        view.hidden = YES;
        view.transform = CGAffineTransformIdentity;
		[view removeConstraintFromSuperview];
        [view removeFromSuperview];
		
        if (_superView)
		{
			[_superView insertSubview:view atIndex:0];
			
			if (_constraint)
			{
				[_superView addConstraints:_constraint];
				_constraint = nil;
			}
			
			[view layoutIfNeeded];
		}
		
		[_overlay removeConstraintFromSuperview];
        [_overlay removeFromSuperview];
		
		if (_handler)
		{
			_handler(YES, user);		//已经结束
			_handler = nil;
		}
    }];
}

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    UITouch *touch = [touches anyObject];
    
    //点击视图区域外将取消弹出
    if (!CGRectContainsPoint(self.subviews.firstObject.frame, [touch locationInView:self]))
    {
		[self viewWithClass:[UITextView class] handler:^(UITextView *view, BOOL *stop) {
			if (view.isFirstResponder)
			{
				[view resignFirstResponder];
				*stop = YES;
			}
		}];
		
		[self viewWithClass:[UITextField class] handler:^(UITextField *view, BOOL *stop) {
			if (view.isFirstResponder)
			{
				[view resignFirstResponder];
				*stop = YES;
			}
		}];
		
        if (_clickDismiss) [self dismissWithAnimated:YES user:NO];
    }
}

@end

#pragma mark - 提示视图

@implementation MRHud

/*===================================================================
 说明:
    初始化
 ==================================================================*/
+ (MRHud *)hud
{
    static MRHud *_hud;
    @synchronized(self)
    {
        if (!_hud)
		{
			_hud = [[NSBundle mainBundle] loadNibNamed:@"MRHudView" owner:nil options:nil][0];
			_hud->_popupView = [MRPopupView new];
			_hud->_popupView.clickDismiss = NO;
			
			_hud.message.numberOfLines = 0;
			_hud.translatesAutoresizingMaskIntoConstraints = NO;
			
			[_hud setBorderWithWidth:1.5 radius:15 color:rgba(255,255,255, .9)];
		}
		
        return _hud;
    }
}

/*===================================================================
 说明:
    根据大小自动更新框架
 ==================================================================*/
- (void)updateFrame
{
	if (!_layoutWidth)		//大小约束
	{
		_layoutWidth = [NSLayoutConstraint constraintWithItem:self attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:nil attribute:0 multiplier:1 constant:77];
		_layoutHieght = [NSLayoutConstraint constraintWithItem:self attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:0 multiplier:1 constant:77];
		
		[self addConstraints:@[_layoutWidth, _layoutHieght]];
		[self layoutIfNeeded];
	}
	
    [UIView animateWithDuration:.15 animations:^{
		
        CGFloat height = 37 + 40;
		CGFloat width = 37 + 40;
		
        if (self.message.text)     //计算字符串宽度
        {
			//CGSize size = [self.message.text sizeWithAttributes:@{NSFontAttributeName:self.message.font}];
			CGSize size = [self.message textRectForBounds:CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.width * .8, 20) limitedToNumberOfLines:0].size;
			width = size.width + 30;
			height = size.height + 77;
			
			if (width < height) width = height;
        }
        
        _layoutWidth.constant  = width;
        _layoutHieght.constant = height;
        [self layoutIfNeeded];
        
        [self.layer setCornerRadius:height / 8];
    }];
}

+ (BOOL)visible
{
    return ![MRHud hud]->_popupView.hidden;
}

+ (void)setBlurRadius:(CGFloat)radius withColor:(UIColor *)color
{
	MRPopupView *pv = [MRHud hud]->_popupView;
	
	pv.blurRadius = radius;
	pv.blurColor  = color;
}

#pragma mark - 显示指示器
/*===================================================================
 说明:
    显示
 ==================================================================*/
- (void)showMe
{
    if (_popupView.hidden)
    {
        [_popupView showView:self superview:nil style:MRPopupStyleAlert size:CGSizeZero handler:nil];
        self.center = _popupView.center;
    }
	[self updateFrame];
}

+ (void)show
{
    [MRHud showWithMessage:nil];
}

+ (void)showWithMessage:(NSString *)string
{
    [[MRHud hud].imageView setHidden:YES];
    [[MRHud hud].indicator startAnimating];
    [[MRHud hud].message setText:string];
    [[MRHud hud] showMe];
}

+ (void)showProgressWithMessage:(NSString *)string
{
    [[MRHud hud].indicator stopAnimating];
    [[MRHud hud].imageView.imgLayer setProgress:0];
    [[MRHud hud].imageView.imgLayer setImgStyle:IMAGE_PROGRESS];
    [[MRHud hud].imageView setHidden:NO];
	[[MRHud hud].message setText:string];
    [[MRHud hud] showMe];
}

/*===================================================================
 说明:
    更新进度值
 ==================================================================*/
+ (void)updateProgress:(CGFloat)progress
{
    dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, NSEC_PER_MSEC);
    dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
        [[MRHud hud].imageView.imgLayer setProgress:progress];
    });
}

#pragma mark - 结束指示器
/*===================================================================
 说明:
    结束
 ==================================================================*/
+ (void)dismiss
{
    [[MRHud hud]->_popupView dismiss];
}

+ (void)dismissWithAnimated:(BOOL)animated
{
	[[MRHud hud]->_popupView dismissWithAnimated:animated];
}

+ (void)dismissWithSuccess:(NSString *)string
{
    [MRHud dismissWithSuccess:string afterDelay:DEFAULT_AFTERDELAY];
}

+ (void)dismissWithSuccess:(NSString *)string afterDelay:(CGFloat)afterDelay
{
    [[MRHud hud].indicator stopAnimating];
    [[MRHud hud].imageView.imgLayer setImgStyle:IMAGE_SUCCESS];
    [[MRHud hud].message setText:string];
    
    [[MRHud hud].imageView setHidden:NO];
    [[MRHud hud] updateFrame];
    
    [self performSelector:@selector(dismiss) withObject:nil afterDelay:afterDelay];
}

+ (void)dismissWithFailure:(NSString *)string
{
    [MRHud dismissWithFailure:string afterDelay:DEFAULT_AFTERDELAY];
}

+ (void)dismissWithFailure:(NSString *)string afterDelay:(CGFloat)afterDelay
{
    [[MRHud hud].indicator stopAnimating];
    [[MRHud hud].imageView.imgLayer setImgStyle:IMAGE_FAILURE];
    [[MRHud hud].message setText:string];
    
    [[MRHud hud].imageView setHidden:NO];
    [[MRHud hud] updateFrame];
    
    [self performSelector:@selector(dismiss) withObject:nil afterDelay:afterDelay];
}

#pragma mark - 显示并自结束指示器
/*===================================================================
 说明:
    显示并延时结束
 ==================================================================*/
+ (void)showWithSuccess:(NSString *)string
{
    [MRHud showWithSuccess:string afterDelay:DEFAULT_AFTERDELAY];
}

+ (void)showWithSuccess:(NSString *)string afterDelay:(CGFloat)afterDelay
{
    [[MRHud hud].indicator stopAnimating];
    [[MRHud hud].message setText:string];
    [[MRHud hud].imageView setHidden:NO];
    [[MRHud hud].imageView.imgLayer setImgStyle:IMAGE_SUCCESS];
    [[MRHud hud] showMe];
    
    [self performSelector:@selector(dismiss) withObject:nil afterDelay:afterDelay];
}

+ (void)showWithFailure:(NSString *)string
{
    [MRHud showWithFailure:string afterDelay:DEFAULT_AFTERDELAY];
}

+ (void)showWithFailure:(NSString *)string afterDelay:(CGFloat)afterDelay
{
    [[MRHud hud].indicator stopAnimating];
    [[MRHud hud].message setText:string];
    [[MRHud hud].imageView setHidden:NO];
    [[MRHud hud].imageView.imgLayer setImgStyle:IMAGE_FAILURE];
    [[MRHud hud] showMe];
    
    [self performSelector:@selector(dismiss) withObject:nil afterDelay:afterDelay];
}

@end
